﻿using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using ZH.GPT.CustomFilter;
using ZH.GPT.Infrastructures;
using ZH.GPT.Infrastructures.Extension;
using ZH.GPT.Infrastructures.Repositories;
using ZH.GPT.Infrastructures.Repositories.Interface;
using ZH.GPT.Services.Interface;
using ZH.GPT.Utils;
using ZH.GPT.Version;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using ZH.RetailContainer.CommLibrary.Consul;
using ZH.RetailContainer.RedisLibrary;
using ZH.GPT.Services;

namespace ZH.GPT.Extend
{
    /// <summary>
    /// IServiceCollection扩展
    /// </summary>
    public static class IServiceCollectionExtend
    {
        /// <summary>
        /// 注入
        /// </summary>
        /// <param name="services">IServiceCollection</param>
        public static void IOC(this IServiceCollection services)
        {
            services.AddControllersWithViews(
            options =>
            {
                //options.Filters.Add<CustomActionFilterAttribute>();
                options.Filters.Add<CustomExceptionFilterAttribute>();
            });

            services.AddTransient<IUserService, UserService>();
            services.AddTransient<IUserRepository, UserRepository>();
            services.AddTransient<IChatService, ChatService>();
            services.AddTransient<IChatRepository, ChatRepository>();
            services.AddTransient<DbContext, MainDBContext>();
            services.AddTransient<IDbContextFactory, DbContextFactory>();
            services.AddScoped<MyContentResult>();
      
        }

        /// <summary>
        /// api文档服务注册
        /// </summary>
        /// <param name="services"></param>
        public static void AddSwagger(this IServiceCollection services)
        {
            services.AddSwaggerGen(options =>
            {
                //遍历出全部的版本，做文档信息展示
                typeof(Version.CustomApiVersion.ApiVersions).GetEnumNames().ToList().ForEach(version =>
                {
                    options.SwaggerDoc(version, new OpenApiInfo
                    {
                        // {ApiName} 定义成全局变量，方便修改
                        Version = version,
                        Title = $"{VersionInfo.ApiName} 接口文档",
                        Description = $"{VersionInfo.ApiName} HTTP API " + version,

                        //TermsOfService = "None",
                        Contact = new OpenApiContact { Name = $"刘工：13484539887", Email = "674945719@qq.com" }
                    });
                    // options.DocumentFilter<SwaggerEnumFilter>();

                });

                // 获取xml文件名
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                // 获取xml文件路径
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                // 添加控制器层注释，true表示显示控制器注释
                //options.DocumentFilter<EnumSchemaFilter>();

                options.DocumentFilter<SwaggerEnumFilter>();//添加过滤器
                options.IncludeXmlComments(xmlPath, true);



            });
        }

        /// <summary>
        /// 引入Swagger
        /// </summary>
        /// <param name="app"></param>
        public static void UseSwaggers(this IApplicationBuilder app)
        {
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                //c.SwaggerEndpoint("/swagger/v1/swagger.json", "ZH.GPT v1");
                //根据版本名称倒序 遍历展示
                typeof(CustomApiVersion.ApiVersions).GetEnumNames()
                //.OrderByDescending(e => e)
                .OrderBy(x => x)
                .ToList().ForEach(version =>
                {
                    c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{VersionInfo.ApiName} {version}");

                });

            });
        }

        /// <summary>
        /// 获取Consul里面的服务地址
        /// </summary>
        /// <param name="services"></param>
        public static void GetConsulUrl(this IServiceCollection services)
        {
            ConsulHelper.Start(services.BuildServiceProvider().CreateScope().ServiceProvider.GetService<IConfiguration>());
        }

        /// <summary>
        /// 添加redis
        /// </summary>
        /// <param name="services"></param>
        /// <param name="connectionString"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public static IServiceCollection AddRedis(this IServiceCollection services, string connectionString, int db = 0)
        {
            services.AddSingleton<IConnectionMultiplexer>(provider =>
            ConnectionMultiplexer.Connect(connectionString));
            services.AddTransient<IRedisService, RedisService>(sp =>
            {
                var multiplexer = sp.GetService<IConnectionMultiplexer>();
                return new RedisService(multiplexer, db);
            });
            return services;
        }


        /// <summary>
        /// 使用环境变量中的配置，更换配置文件中的数据库配置
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void RefreshConfigurationByEnvironment(this IServiceCollection services, IConfiguration configuration)
        {
            //数据库配置
            configuration.SetConfigurationByEnvironment("ConnectionStrings:MasterConnection", "ConnectionStrings_MasterConnection");
            configuration.SetConfigurationsByEnvironment("ConnectionStrings:SlaveConnectionList", "ConnectionStrings_SlaveConnectionList");

            //consul
            configuration.SetConfigurationByEnvironment("ConsulService:IP", "ConsulService_IP");
            configuration.SetConfigurationByEnvironment("ConsulService:Port", "ConsulService_Port");
            configuration.SetConfigurationByEnvironment("ConsulService:ConsulAddress", "ConsulService_ConsulAddress");

            //log
            configuration.SetConfigurationByEnvironment("AccessKey", "AccessKey");
            configuration.SetConfigurationByEnvironment("AccessKeySecret", "AccessKeySecret");
            configuration.SetConfigurationByEnvironment("Project", "Project");
            configuration.SetConfigurationByEnvironment("LogStoreName", "LogStoreName");

            //redis
            configuration.SetConfigurationByEnvironment("Redis:Host", "Redis_Host");
            configuration.SetConfigurationByEnvironment("Redis:Port", "Redis_Port");
            configuration.SetConfigurationByEnvironment("Redis:Password", "Redis_Password");
        }

    }
}
